package dao

import (
	"context"
	"encoding/json"
	"gorm.io/gorm"
	"inventory/api/inventory"
	"inventory/internal/constant"
	"time"

	"inventory/internal/model"
)

// FindAllWarehousesByPage 全部仓库分页获取
func (d *Dao) FindAllWarehousesByPage(ctx context.Context, pageNo, pageSize int) (warehouses []*model.Warehouse, err error) {
	var db *gorm.DB
	// 总部模式不需要过滤门店仓
	db = d.TransContext(ctx).Model(&model.Warehouse{}).Where("status != ?", constant.WarehouseDeleted)
	err = db.Order("id asc").Offset((pageNo - 1) * pageSize).Limit(pageSize).Find(&warehouses).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// GetMonthlyStatsByMonth 月报表
func (d *Dao) GetMonthlyStatsByMonth(ctx context.Context, warehouseID uint32, month string) (statsMonthly []*model.StatsMonthly, err error) {
	err = d.TransContext(ctx).Model(model.StatsMonthly{}).Where("month = ? and warehouse_id = ?",
		month, warehouseID).Find(&statsMonthly).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// GetMonthlyStatsByMonthAndStorageKey 根据月份跟storageKey获取报表
func (d *Dao) GetMonthlyStatsByMonthAndStorageKey(ctx context.Context, warehouseID uint32, month string,
	storageKey string) (statsMonthly *model.StatsMonthly, err error) {
	statsMonthly = &model.StatsMonthly{}
	err = d.TransContext(ctx).Model(model.StatsMonthly{}).Where("month = ? and warehouse_id = ? and storage_key = ?",
		month, warehouseID, storageKey).Take(&statsMonthly).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// GetMonthlyStatsByMonthWithStorageType 根据月份跟storageType获取报表
func (d *Dao) GetMonthlyStatsByMonthWithStorageType(ctx context.Context, warehouseID uint32, month string,
	storageType int) (statsMonthly []*model.StatsMonthly, err error) {
	db := d.TransContext(ctx).Model(model.StatsMonthly{}).Where("month = ? and warehouse_id = ?",
		month, warehouseID)
	if storageType != 0 {
		db.Where("storage_type = ?", storageType)
	}
	err = db.Find(&statsMonthly).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// GetLastMonthStoragePriceByStorageKeys 获取上月期末加权单价
func (d *Dao) GetLastMonthStoragePriceByStorageKeys(ctx context.Context, warehouseID uint32, storageKeys []string, now time.Time,
	materialRemarks map[string]*model.FullRemark, unitType int) (
	priceMap map[string]uint64, err error) {
	month := now.AddDate(0, -1, 0).Format("2006-01")
	var statsMonthly []*model.StatsMonthly
	err = d.TransContext(ctx).Model(model.StatsMonthly{}).Where("month = ? and warehouse_id = ? and storage_key in ?",
		month, warehouseID, storageKeys).Find(&statsMonthly).Error
	if err != nil {
		err = d.processSqlError(err)
		return
	}
	priceMap = make(map[string]uint64)
	for _, record := range statsMonthly {
		var remark model.StorageRealTimeRemark
		if err = json.Unmarshal(record.Remark, &remark); err != nil {
			return
		}
		if record.StorageType == uint8(inventory.StorageType_MATERIAL) {
			if materialRemark, ok := materialRemarks[record.StorageKey]; ok {
				// 加载快照库存换算比，结合当前换算比，输出当前单位下的价格
				switch unitType {
				case constant.UnitTypePurchase:
					priceMap[record.StorageKey] = uint64(float64(record.Price) *
						materialRemark.PurchaseRatio / remark.StorageRatio)
				case constant.UnitTypeStorage:
					priceMap[record.StorageKey] = uint64(float64(record.Price) *
						materialRemark.StorageRatio / remark.StorageRatio)
				default:
					priceMap[record.StorageKey] = uint64(record.Price)
				}
				continue
			}

		}
		priceMap[record.StorageKey] = uint64(record.Price)
	}
	return
}

// GetReversedDailyStatsByMonth 获取反结账报表
func (d *Dao) GetReversedDailyStatsByMonth(ctx context.Context, warehouseID uint32, start, end time.Time) (
	statsDailyViews []*model.DailyStatsView, err error) {
	err = d.TransContext(ctx).Model(model.StatsDaily{}).Select(
		"storage_key, storage_type, action_type, quantity, amount").Where(
		"record_date between ? and ? and warehouse_id = ?",
		start, end, warehouseID).Order("id desc").Find(&statsDailyViews).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}

// GetDailyStats 获取日报表
func (d *Dao) GetDailyStats(ctx context.Context, warehouseID uint32, storageKey string, start, end time.Time) (
	statsDaily []*model.StatsDaily, err error) {
	err = d.TransContext(ctx).Model(model.StatsDaily{}).Where(
		"record_date between ? and ? and warehouse_id = ? and storage_key = ?",
		start, end, warehouseID, storageKey).Find(&statsDaily).Error
	if err != nil {
		err = d.processSqlError(err)
	}
	return
}
